
// use nebula engine memory
#define USE_NEBULA_MEMORY 1

//use zt engine memory
#define USE_ZT_MEMORY     0


/*
	Helper function for heap16 functions: aligns pointer to l6 byte and
	writes padding mask to byte before returned pointer.
*/
__forceinline unsigned char*
__HeapAlignPointerAndWritePadding16(unsigned char* ptr)
{
	unsigned char paddingMask = DWORD(ptr) & 15;
	ptr = (unsigned char*)(DWORD(ptr + 16) & ~15);
	ptr[-1] = paddingMask;
	return ptr;
}

/*
	Helper function for heap16 functions: "un-aligns" pointer through
	the padding mask store in the byte before the pointer
*/
__forceinline unsigned char*
__HeapUnalignPointer16(unsigned char* ptr)
{
	return (unsigned char*)(DWORD(ptr - 16) | ptr[-1]);
}

/* HeapAlloc replacement which always returns 16-bytes aligned address
	NOTE: only works for 32 bit pointers!
*/
__forceinline LPVOID
__HeapAlloc16(HANDLE hHeap, DWORD dwFlags, size_t dwBytes)
{
	unsigned char* ptr = (unsigned char*)::HeapAlloc(hHeap, dwFlags, dwBytes+16);
	ptr = __HeapAlignPointerAndWritePadding16(ptr);
	return (LPVOID)ptr;
}


/*
	HeapReAlloc replacement for 16-byte alignment
	NOTE: only works for 32 bit pointers
*/
__forceinline LPVOID
__HeapReAlloc16(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, size_t dwBytes)
{
	//restore unaligned pointer
	unsigned char* ptr = (unsigned char*)lpMem;
	unsigned char* rawPtr = __HeapUnalignPointer16(ptr);

	ptr = (unsigned char*)::HeapReAlloc(hHeap, (dwFlags | HEAP_REALLOC_IN_PLACE_ONLY), rawPtr, dwBytes+16);
	if(0 == ptr)
	{
		DWORD rawSize = ::HeapSize(hHeap, dwFlags, rawPtr);
		ptr = (unsigned char*) ::HeapAlloc(hHeap, dwFlags, dwBytes+16);
		ptr = __HeapAlignPointerAndWritePadding16(ptr);
		DWORD copySize = dwBytes <= (rawSize - 16) ? dwBytes : (rawSize - 16);
		::CopyMemory(ptr, lpMem, copySize);
		::HeapFree(hHeap, dwFlags, rawPtr);
	}
	else
	{
		ptr = __HeapAlignPointerAndWritePadding16(ptr);
	}

	return (LPVOID)ptr;
}

/*
	HeapFree replacement which always returns 16-byte aligned address
	NOTE: only works for 32 bit pointers
*/
__forceinline BOOL
__HeapFree16(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
{
	unsigned char* ptr = (unsigned char*)lpMem;
	ptr = __HeapUnalignPointer16(ptr);
	return ::HeapFree(hHeap, dwFlags, ptr);
}

/*
	HeapSize replacement which always returns 16-byte aligned address
	NOTE: only works for 32 bit pointers
*/
__forceinline size_t
__HeapSize16(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem)
{
	unsigned char* ptr = (unsigned char*) lpMem;
	ptr = __HeapUnalignPointer16(ptr);
	return ::HeapSize(hHeap, dwFlags, ptr);
}